#include "segmentation.h"
#include <QDebug>

#include <QFile>
#include <QString>
#include <QTextStream>
#include <QRegExp>
#include <cmath>

Segmentation::Segmentation(){
    m_Data = NULL;
    m_SegData = NULL;
    m_Segments = NULL; //Red-not processed, Black-not a region, White-region
    allSegments = false;
}

void Segmentation::DisplaySegment(int x, int y){
    if(m_Segments->pixel(x,y)==qRgb(255,255,255)){
        m_SegData->setPixel(x,y,white);
        qDebug()<<"jest w białym";


                PutMask(x,y);


    }
    else
        return;
    //m_->m_Label->setPixmap(QPixmap::fromImage(*m_Img->m_Fourier->GetData()));
}
void Segmentation::PutMask(int x, int y){
    if(x>=0 && x<m_Data->width() && y>=0 && y<m_Data->height()){;
        if( ( m_Segments->pixel(x,y))== qRgb(255,255,255)){
            qDebug()<<"PutMAsk";
            m_SegData->setPixel(x,y,white);
            PutMask  (x -1, y -1);
            PutMask  (x   , y -1);
            PutMask  (x +1, y -1);
            PutMask  (x -1, y   );
            PutMask  (x +1, y   );
            PutMask  (x -1, y +1);
            PutMask  (x   , y +1);
            PutMask  (x +1, y +1);
        }
        else
            return ;
    }
    else
        return;
}
void Segmentation::Clicked(int x,  int y){
    this->clickedX = x;
    this->clickedY = y;
    qDebug() << "Clicked";
    qDebug() << x;
    qDebug() << y;

    //testing
    m_SegData = new QImage(m_Data->width(), m_Data->height(), m_Data->format());
    m_SegData = m_Data;
}
void Segmentation::SetData(QImage *_data)
{
    m_Data = _data;
}
QImage *Segmentation::GetData() const
{
    return m_SegData;
}
QImage *Segmentation::GetSegments() const
{
    return m_Segments;
}
void Segmentation::AllSegments(bool ifAll){
    allSegments = ifAll;

}
void Segmentation::SetTolerance(int t){
    tolerance = t;
}
void Segmentation::FindSegments(){
    //m_Segments :Red-not processed, Black-not a region, White-region
    int i,j;
    uint segCol;
    //red = 0xFF;
    //red <<= 8;
    //red |= 255;
    //red <<= 8;
    //red |= 0;
    //red <<= 8;
    //red |= 0;
    m_Segments = new QImage(m_Data->width(), m_Data->height(), m_Data->format());
    for(i=0; i<m_Data->width();i++){
        for(j=0; j<m_Data->height();j++){
            m_Segments->setPixel(i,j,red);
        }
    }
    qDebug()<<tolerance;

    if(m_Data->allGray()){
        uint col = m_Data->pixel(clickedX,clickedY);
        uint base= (col >> 16) & 255; // 255
        if(!allSegments){
            segCol = qRgb((int)(rand() % 255 + 1),(int)(rand() % 255 + 1),(int)(rand() % 255 + 1));
            CheckPoint(clickedX,clickedY,base,qRgb(255,255,255));
            for(i=0; i<m_Data->width();i++){
                for(j=0; j<m_Data->height();j++){
                    if( m_Segments->pixel(i,j) == qRgb(255,0,0)){
                        m_Segments->setPixel(i,j,black);
                    }
                }
            }
        }
        else{
            segCol = qRgb((int)(rand() % 255 + 1),(int)(rand() % 255 + 1),(int)(rand() % 255 + 1));
            CheckPoint(clickedX,clickedY,base,segCol);
            for(i=0; i<m_Data->width();i++){
                for(j=0; j<m_Data->height();j++){
                    if( m_Segments->pixel(i,j) == qRgb(255,0,0)){
                        segCol = qRgb((int)(rand() % 255 + 1),(int)(rand() % 255 + 1),(int)(rand() % 255 + 1));
                        CheckPoint(i,j,base,segCol);
                    }
                }
            }
        }
    }
    else{
        uint col = m_Data->pixel(clickedX,clickedY);
        uint baseR= (col >> 16) & 255; // 255
        uint baseG= (col >> 8) & 255; // 255
        uint baseB= col & 255; // 255
        if(!allSegments){
            segCol = qRgb((int)(rand() % 255 + 1),(int)(rand() % 255 + 1),(int)(rand() % 255 + 1));
            CheckPointRGB(clickedX,clickedY,baseR,baseG,baseB,segCol);
            for(i=0; i<m_Data->width();i++){
                for(j=0; j<m_Data->height();j++){
                    if( m_Segments->pixel(i,j) == qRgb(255,0,0)){
                        m_Segments->setPixel(i,j,black);
                    }
                }
            }
        }
        else{
            segCol = qRgb((int)(rand() % 255 + 1),(int)(rand() % 255 + 1),(int)(rand() % 255 + 1));
            CheckPointRGB(clickedX,clickedY,baseR,baseG,baseB,segCol);
            for(i=0; i<m_Data->width();i++){
                for(j=0; j<m_Data->height();j++){
                    if( m_Segments->pixel(i,j) == qRgb(255,0,0)){
                        CheckPointRGB(i,j,baseR,baseG,baseB,segCol);
                    }
                }
            }
        }
    }
}

void Segmentation::CheckPoint(int x, int y, uint base, uint segCol){
    if(x>=0 && x<m_Data->width() && y>=0 && y<m_Data->height()){
        if( m_Segments->pixel(x,y) == qRgb(255,0,0)){
            if((((m_Data->pixel(x,y)>> 16) & 255) <= base+tolerance) && ( ((m_Data->pixel(x,y)>> 16) & 255)>=base-tolerance)){
                    m_Segments->setPixel(x,y,white);
                    m_SegData->setPixel(x,y,segCol);

            }
            else{
                m_Segments->setPixel(x,y,black);
                return ;
            }
        }
        else
            return ;


        CheckPoint  (x -1, y -1, base,segCol);
        CheckPoint  (x   , y -1, base,segCol);
        CheckPoint  (x +1, y -1, base,segCol);
        CheckPoint  (x -1, y   , base,segCol);
        CheckPoint  (x +1, y   , base,segCol);
        CheckPoint  (x -1, y +1, base,segCol);
        CheckPoint  (x   , y +1, base,segCol);
        CheckPoint  (x +1, y +1, base,segCol);
    }
    else
        return;

}

void Segmentation::CheckPointRGB(int x, int y, uint baseR, uint baseG, uint baseB,uint segCol){
    if(x>=0 && x<m_Data->width() && y>=0 && y<m_Data->height()){
        if( ((( m_Segments->pixel(x,y)) >> 16) & 255) != black){
            if( m_Segments->pixel(x,y) == qRgb(255,0,0)){
                if((((m_Data->pixel(x,y)>> 16) & 255) <= baseR+tolerance) && (((m_Data->pixel(x,y)>> 8) & 255) <= baseG+tolerance) && ((m_Data->pixel(x,y) & 255) <= baseB+tolerance)){
                    if((((m_Data->pixel(x,y)>> 16) & 255)>= baseR-tolerance) && (((m_Data->pixel(x,y)>> 8) & 255) >= baseG-tolerance) && ((m_Data->pixel(x,y) & 255) >= baseB-tolerance)){
                        m_Segments->setPixel(x,y,white);
                        m_SegData->setPixel(x,y,segCol);
                    }
                    else{
                        m_Segments->setPixel(x,y,black);
                        return ;
                    }
                }
                else{
                    m_Segments->setPixel(x,y,black);
                    return ;
                }
            }
            else
                return ;


            CheckPointRGB  (x -1, y -1, baseR,baseG,baseB,segCol);
            CheckPointRGB  (x   , y -1, baseR,baseG,baseB,segCol);
            CheckPointRGB  (x +1, y -1, baseR,baseG,baseB,segCol);
            CheckPointRGB  (x -1, y   , baseR,baseG,baseB,segCol);
            CheckPointRGB  (x +1, y   , baseR,baseG,baseB,segCol);
            CheckPointRGB  (x -1, y +1, baseR,baseG,baseB,segCol);
            CheckPointRGB  (x   , y +1, baseR,baseG,baseB,segCol);
            CheckPointRGB  (x +1, y +1, baseR,baseG,baseB,segCol);
        }
        else
            return;
    }
    else
        return;
}

bool Segmentation::InRegionGrey(int x, int y, uint base){


    //var g:uint = (color >> 8) & 255; // 122
    //var b:uint = color & 255; // 15
    qDebug() << "w InRegionGrey";
    if(x>=0 && x<m_Data->width() && y>=0 && y<m_Data->height()){
        uint col = m_Data->pixel(x,y);
        uint r= (col >> 16) & 255; // 255

        if( m_Segments->pixel(x,y) == qRgb(255,0,0)){
            if(r<=base+tolerance){
                if( r>=base-tolerance){
                    m_Segments->setPixel(x,y,white);
                    return true;
                }
                else{
                    m_Segments->setPixel(x,y,black);
                    return false;
                }
            }
            else{
                m_Segments->setPixel(x,y,black);
                return false;
            }
        }
        else
            return false;
    }
    else
        return false;
}
